#include <54func.h>

typedef struct dir_s {
    char dName[64];
    struct dir_s *pFront;
    struct dir_s *pNext;
} dir_t;
typedef struct dirStack_s {
    dir_t *pTop;
    dir_t *pBottom;
    int stackSize;
} dirStack_t;
//bottom <-> top
int initStack(dirStack_t *pStack){
    bzero(pStack, sizeof(pStack));
    return 0;
}
int pushStack(dirStack_t *pStack, char *dirName){
    dir_t *pNew = (dir_t *)calloc(1, sizeof(dir_t));
    strncpy(pNew->dName, dirName, sizeof(pNew->dName));

    if(pStack->stackSize == 0){
        pStack->pTop = pNew;
        pStack->pBottom = pNew;
    }
    else{
        pNew->pFront = pStack->pTop;
        pStack->pTop->pNext = pNew;
        pStack->pTop = pNew;
    }
    ++pStack->stackSize;

    return 0;
}
int popStack(dirStack_t *pStack){
    dir_t *pTemp = pStack->pTop;
    pStack->pTop = pStack->pTop->pFront;
    pStack->pTop->pNext = NULL;
    free(pTemp);

    --pStack->stackSize;
    if(pStack->stackSize == 0){
        pStack->pBottom = NULL;
    }

    return 0;
}
int visitStack(dirStack_t *pStack){
    printf("visit stack: size = %d, ", pStack->stackSize);
    dir_t *pCur = pStack->pBottom;
    int size = pStack->stackSize;
    while(size){
        printf("/%s", pCur->dName);
        pCur = pCur->pNext;
        --size;
    }
    printf("\n");
}
int handle_path(dirStack_t *pStack, char *path){
    char *temp = strtok(path, "/");
    //printf("%s\n", temp);
    if(temp != NULL){
        pushStack(pStack, temp);
        //printf("Stack:\n");
        //visitStack(pStack);
        //printf("---------------------------\n");
    }
    while((temp = strtok(NULL, "/")) != NULL){
        pushStack(pStack, temp);
        //printf("Stack:\n");
        //visitStack(pStack);
        //printf("---------------------------\n");
    }

    return 0;
}
int myGetcwd(dirStack_t *pStack, char *buf){
    int size = pStack->stackSize - 2;

    bzero(buf, sizeof(buf));
    buf[0] = '~';
    dir_t *pCur = pStack->pBottom->pNext->pNext;

    while(size){
        strcat(buf, "/");
        strcat(buf, pCur->dName);
        //sprintf(buf, "%s/%s", buf, pCur->dName);
        //printf("after sprintf: %s\n", buf);
        pCur = pCur->pNext;
        //printf("pCur->dName: %s\n", pCur->dName);
        --size;
    }
    //sprintf(buf, "/%s", buf);

    return 0;
}
int handle_cd(dirStack_t *pStack, char *arg){
    if(arg[0] == '.' && strlen(arg) == 1){
        printf("[into case 1]\n");
        // do nothing
        return 0;
    }
    else if(arg[0] == '\0' 
            || (arg[0] == '~' && strlen(arg) == 1)){
        // to home 
        printf("[into case 2]\n");
        dir_t *pCur = pStack->pBottom;
        char homePath[256] = {0};

        for(int i = 0; i < 2; ++i){
            strcat(homePath, "/");
            strcat(homePath, pCur->dName);
            pCur = pCur->pNext;
        }

        int ret = chdir(homePath);
        printf("chdir ret = %d\n", ret);
        char *cwd = getcwd(NULL, 0);
        printf("cwd after chdir: %s\n", cwd);
        if(ret != 0){
            return -1;
        }
        else{
            while(pStack->stackSize > 2){
                popStack(pStack);
            }
            visitStack(pStack);
            return 0;
        }
    }
    else if(arg[0] == '.' && arg[1] == '.' && strlen(arg) ==2){
        // to parent
        printf("[into case 3]\n");
        printf("cwd: %s\n", getcwd(NULL, 0));
        if(pStack->stackSize == 2){
            return 0;
        }
        dir_t *pCur = pStack->pBottom;
        char parentPath[256] = {0};

        for(int i = 0; i < pStack->stackSize - 1; ++i){
            strcat(parentPath, "/");
            strcat(parentPath, pCur->dName);
            pCur = pCur->pNext;
        }

        int ret = chdir(parentPath);
        printf("chdir ret = %d\n", ret);
        char *cwd = getcwd(NULL, 0);
        printf("cwd after chdir: %s\n", cwd);
        if(ret != 0){
            return -1;
        }
        else{
            popStack(pStack);
            visitStack(pStack);
            return 0;
        }
    }
    else{
        // other path
        printf("[into case 4]\n");
        printf("-----\n");
        dir_t *pCur = pStack->pBottom;
        if(arg[0] == '.'){
            arg[0] = '/';
        }

        char newPath[256] = {0};
        strncpy(newPath, getcwd(NULL, 0), sizeof(newPath));
        char *temp = strtok(arg, "/");
        if(temp == NULL){
            return -1;
        }
        strcat(newPath, "/");
        strcat(newPath, temp);
        //printf("newPath = %s\n", newPath);
        int ret = chdir(newPath);
        printf("chdir ret = %d\n", ret);
        char *cwd = getcwd(NULL, 0);
        printf("cwd after chdir: %s\n", cwd);
        if(ret != 0){
            return -1;
        }
        else{
            pushStack(pStack, temp);
            visitStack(pStack);
            printf("-----\n");
        }

        while((temp = (strtok(NULL, "/"))) != NULL){
            pCur = pStack->pBottom;
            //printf("temp = %s\n", temp);
            bzero(newPath, sizeof(newPath));

            if(strncmp(temp, "..", 2) == 0){
                if(pStack->stackSize == 2){
                    continue;
                }

                for(int i = 0; i < pStack->stackSize - 1; ++i){
                    strcat(newPath, "/");
                    strcat(newPath, pCur->dName);
                    pCur = pCur->pNext;
                }
                //printf("newPath = %s\n", newPath);

                int ret = chdir(newPath);
                printf("chdir ret = %d\n", ret);
                char *cwd = getcwd(NULL, 0);
                printf("cwd after chdir: %s\n", cwd);
                if(ret != 0){
                    return -1;
                }
                else{
                    popStack(pStack);
                    visitStack(pStack);
                    printf("-----\n");
                }
            }
            else{
                for(int i = 0; i < pStack->stackSize; ++i){
                    strcat(newPath, "/");
                    strcat(newPath, pCur->dName);
                    pCur = pCur->pNext;
                }
                strcat(newPath, "/");
                strcat(newPath, temp);

                int ret = chdir(newPath);
                printf("chdir ret = %d\n", ret);
                char *cwd = getcwd(NULL, 0);
                printf("cwd after chdir: %s\n", cwd);
                if(ret != 0){
                    return -1;
                }
                else{
                    pushStack(pStack, temp);
                    visitStack(pStack);
                    printf("-----\n");
                }
            }
        }
    }

    return 0;
}
//int main(int argc, char *argv[]){
//    dirStack_t dirStack;
//    initStack(&dirStack);
//
//    char *cwd = getcwd(NULL, 0);
//    printf("getcwd: %s\n", cwd);
//    printf("-----\n");
//
//    handle_path(&dirStack, cwd); // push path into stack
//
//    while(1){
//        char arg[256] = {0};
//        printf("Enter path:\n");
//        fgets(arg, sizeof(arg), stdin);
//        arg[strlen(arg) - 1] = '\0';
//
//        int ret = handle_cd(&dirStack, arg);
//        printf("handle_cd ret = %d\n", ret);
//        printf("--------------------------\n");
//    }
//
//    return 0;
//}


